﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace AwesomeEnginePC.Graphics.TwoDimensional.Sprites
{
    public class PixelCollision
    {
        public PixelCollision()
        {

        }

        public bool CollidesWith(BaseSprite source, BaseSprite other)
        {
            // Default behavior uses per-pixel collision detection
            return CollidesWith(source, other, true);
        }

        public bool CollidesWith(BaseSprite source, BaseSprite other, bool calcPerPixel)
        {
            // Get dimensions of texture
            int widthOther = other.Width;
            int heightOther = other.Height;
            int widthMe = source.Width;
            int heightMe = source.Height;

            if (calcPerPixel &&                                // if we need per pixel
                ((Math.Min(widthOther, heightOther) > 100) ||  // at least avoid doing it
                (Math.Min(widthMe, heightMe) > 100)))          // for small sizes (nobody will notice :P)
            {
                return source.boundingRectangle.Intersects(other.boundingRectangle) // If simple intersection fails, don't even bother with per-pixel
                    && PerPixelCollision(source, other);
            }

            return source.boundingRectangle.Intersects(other.boundingRectangle);
        }

        static bool PerPixelCollision(BaseSprite a, BaseSprite b)
        {

            // Calculate the intersecting rectangle
            int x1 = Math.Max(a.boundingRectangle.X, b.boundingRectangle.X);
            int x2 = Math.Min(a.boundingRectangle.X + a.boundingRectangle.Width, b.boundingRectangle.X + b.boundingRectangle.Width);

            int y1 = Math.Max(a.boundingRectangle.Y, b.boundingRectangle.Y);
            int y2 = Math.Min(a.boundingRectangle.Y + a.boundingRectangle.Height, b.boundingRectangle.Y + b.boundingRectangle.Height);

            // For each single pixel in the intersecting rectangle
            for (int y = y1; y < y2; ++y)
            {
                for (int x = x1; x < x2; ++x)
                {
                    // Get the color from each texture
                    Color aColor = a.TextureData[(x - a.boundingRectangle.X) + (y - a.boundingRectangle.Y) * a.Width];
                    Color bColor = b.TextureData[(x - b.boundingRectangle.X) + (y - b.boundingRectangle.Y) * b.Width];

                    if (aColor.A != 0 && bColor.A != 0) // If both colors are not transparent (the alpha channel is not 0), then there is a collision
                    {
                        return true;
                    }
                }
            }
            // If no collision occurred by now, we're clear.
            return false;
        }
        /// <summary>
        /// Determines if there is overlap of the non-transparent pixels
        /// between two sprites.
        /// </summary>
        /// <param name="rectangleA">Bounding rectangle of the first sprite</param>
        /// <param name="dataA">Pixel data of the first sprite</param>
        /// <param name="rectangleB">Bouding rectangle of the second sprite</param>
        /// <param name="dataB">Pixel data of the second sprite</param>
        /// <returns>True if non-transparent pixels overlap; false otherwise</returns>
        public bool IntersectPixels(Rectangle rectangleA, Color[] dataA,
                                    Rectangle rectangleB, Color[] dataB)
        {
            // Find the bounds of the rectangle intersection
            int top = Math.Max(rectangleA.Top, rectangleB.Top);
            int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
            int left = Math.Max(rectangleA.Left, rectangleB.Left);
            int right = Math.Min(rectangleA.Right, rectangleB.Right);

            // Check every point within the intersection bounds
            for (int y = top; y < bottom; y++)
            {
                for (int x = left; x < right; x++)
                {
                    // Get the color of both pixels at this point
                    Color colorA = dataA[(x - rectangleA.Left) +
                                         (y - rectangleA.Top) * rectangleA.Width];
                    Color colorB = dataB[(x - rectangleB.Left) +
                                         (y - rectangleB.Top) * rectangleB.Width];

                    // If both pixels are not completely transparent,
                    if (colorA.A != 0 && colorB.A != 0)
                    {
                        // then an intersection has been found
                        return true;
                    }
                }
            }

            // No intersection found
            return false;
        }
    }
}
